package com.apes.framework.plugin.esb.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.SpringManager;
import com.apes.framework.config.jackson.JacksonUtil;
import com.apes.framework.jpa.ApesBean;
import com.apes.framework.jpa.Model;
import com.apes.framework.rop.session.SimpleSession;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.framework.util.Tools;
import com.apes.oap.AbstractRopRequest;
import com.apes.oap.RopRequestContext;
import com.apes.oap.session.RopSessionHolder;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.Assert;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class SimpleRequest extends AbstractRopRequest implements Request {

    @NotNull
    private String body;

    private Object data;

    public void setBody(String body) {
        this.body = body;
    }

    @Override
    public Object getData() {
        return (data == null) ? this.body : data;
    }

    @Override
    public Request setData(Object o) {
        this.data = o;
        return this;
    }

    @Override
    public Map getMap() {
        Object data = getData();
        if (data instanceof Map) return (Map) data;
        return getJO();
    }

    @Override
    public List getList() {
        return getJA();
    }

    @Override
    public String getS() {
        return JSONObject.toJSONString(getData());
    }

    @Override
    public JSONObject getJO() {
        Object o = getJ();
        Assert.isTrue(o instanceof JSONObject, "调用方法：getJO() 错误，数据类型错误。");
        return (JSONObject) o;
    }

    @Override
    public JSONArray getJA() {
        Object o = getJ();
        Assert.isTrue(o instanceof JSONArray, "调用方法：getJA() 错误，数据类型错误。");
        return (JSONArray) o;
    }

    private Object getJ() {
        Object data = getData();
        if (data instanceof String) {
            return Tools.getJO((String) data);
        } else {
            Object o = JSONObject.toJSON(getData());
            Assert.isTrue(o instanceof JSON, "调用方法：getJ() 错误，数据类型错误。");
            return o;
        }
    }

    @Override
    public <T> T get(String key) {
        Map m = getMap();
        Assert.isTrue(m.containsKey(key), "调用方法：get(String key) 错误，key值: " + key + "不存在。");
        return (T) m.get(key);
    }

    public <T> T get(String key, T defaults) {
        Map m = getMap();
        if (m.containsKey(key)) {
            return (T) m.get(key);
        }
        return defaults;
    }

    @Override
    public <T> T getO(Class<T> clazz) {
        Object data = getData();
        if (clazz.isInstance(data)) {
            return (T) data;
        }
        Object o = getJ();
        Assert.isTrue(o instanceof Map, "调用方法：getO() 错误，数据类型错误。");
        T t = Tools.map(o, clazz);
        if (t instanceof ApesBean) {
            SpringManager.getBean(MapUtil.class).refresh(t);
            if (t instanceof Model) ((Model) t).setOperator(getPersonId());
        }
        return t;
    }

    @Override
    public <T> T getO2(Class<T> clazz) {
        Object data = getData();
        if (clazz.isInstance(data)) {
            return (T) data;
        }
        ObjectMapper mapper = JacksonUtil.mapper;
        T t;
        try {
            if (data instanceof String) {
                t = mapper.readValue((String) data, clazz);
            } else {
                t = mapper.convertValue(data, clazz);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (t instanceof ApesBean) {
            SpringManager.getBean(MapUtil.class).refresh(t);
            if (t instanceof Model) ((Model) t).setOperator(getPersonId());
        }
        return t;
    }

    @Override
    public <T> T getO(String key, Class<T> type) {
        Object o = get(key);
        if (type.isInstance(o)) {
            return (T) o;
        }
        Assert.isTrue(o instanceof Map, "调用方法：getO() 错误，数据类型错误。");
        T t = Tools.map(o, type);
        if (t instanceof ApesBean) SpringManager.getBean(MapUtil.class).refresh(t);
        return t;
    }

    @Override
    public List getA(Class type) {
        return getA(type, true);
    }

    @Override
    public List getA(Class type, boolean isNest) {
        Object o = getJ();
        Assert.isTrue(o instanceof List, "调用方法：getA() 错误，数据类型错误。");
        return getList((List<Map>) o, type, isNest);
    }

    @Override
    public List getA(String key, Class type) {
        return getA(key, type, true);
    }

    @Override
    public List getA(String key, Class type, boolean isNest) {
        Object o = get(key);
        Assert.isTrue(o instanceof List, "调用方法：getA() 错误，数据类型错误。");
        return getList((List<Map>) o, type, isNest);
    }

    private List getList(List<Map> o, Class type, boolean isNest) {
        List rows = new ArrayList();
        for (Map row : o) {
            Object bean;
            if (isNest) bean = Tools.map(row, type);  /** 数据类型需要一致 **/
            else bean = Tools.toBean(type, row); /** 数据类型可以不一致 **/
            if (bean instanceof ApesBean) {
                SpringManager.getBean(MapUtil.class).refresh(bean);
                if (bean instanceof Model) ((Model) bean).setOperator(getPersonId());
            }
            rows.add(bean);
        }
        return rows;
    }

    public <T> T getCurrentUser() { //User
        SimpleSession session = getSession();
        if (session == null) return null;
        Integer userId = Integer.valueOf(session.getUserId());
        String topic = "event:aut.user.findOne";
        Map body = MapUtil.mapper("id", userId);
        List users = EventUtil.sendSynEvent(this, topic, body);
        if(users == null || users.isEmpty()) return null;
        return (T) users.stream().findFirst().get();
    }

    public <T> T getPerson() {  //PartyRole
        Object user = getCurrentUser();
        if (user == null) return null;
        T person = ReflectUtil.getFieldValue(user, "person");
//        Assert.notNull(person, "用户没有设置人员信息！");
        return person;
    }

    public String getPersonId() {
        Object person = getPerson();
        if (person == null) return null;
        return ReflectUtil.getFieldValue(person, "id");
    }

    public String getPostId() {
        SimpleSession session = getSession();
        if (session == null) return null;
        return session.getPostId();
    }

    public SimpleSession getSession() {
        RopRequestContext context = getRopRequestContext();
        if (context == null) return null;
        SimpleSession session = (SimpleSession) context.getSession();
        if (session != null) return session;
        session = (SimpleSession) RopSessionHolder.get();
        return session;
    }

    public String getBranchId() {
        SimpleSession session = getSession();
        if (session == null) return null;
        return session.getBranchId();
    }

    public Long getCompanyId(){
        SimpleSession session = getSession();
        if (session == null) return null;
        return session.getCompanyId();
    }

    /***
     * 获取公司对应的PartyRole
     */
    public <T> T getCurrentCompany() {
        SimpleSession session = getSession();
        if (session == null) return null;
        Long companyId = session.getCompanyId();
        String topic = "event:cm.company.findOne";
        Map body = MapUtil.mapper("id", companyId.toString());
        List company = EventUtil.sendSynEvent(this, topic, body);
        if(company == null || company.isEmpty()) return null;
        return (T) company.stream().findFirst().get();
    }
}
